home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
cmln0586.arc
/
POLYGON1.LTG
< prev
Wrap
Text File
|
1986-04-06
|
10KB
|
285 lines
#include <stdio.h>
/* */
/* Polygon Fill Routine - POLYHATCH */
/* */
/* This routine is a Raster Scan Fill which will fill (or hatch) */
/* the object reperesented by the input data. The following */
/* describes the input date: */
/* */
/* COLOR - The current fill color (or pattern) to be used. */
/* POINTS - The co-ordinate pairs for the object (See DTABLE). */
/* NUM_POINTS - The number of coordinate points stored in POINTS. */
/* CROSSHATCH - Global Flag for Solid/Crosshatch Fill Decision */
/* */
#define ROUND_OFF 0.001 /* set comparison tolerence for horz lines */
#define LINE_WIDTH 10.0 /* Width of scan line in coordinate units */
#define MAX_EDGE 1000 /* Maximum number of edges in EDGE_TBL */
#define MAX_PATTERN 16 /* Maximum number of different crosshatchs */
#define INTER1 8*LINE_WIDTH /* Interval between lines for crosshatch */
#define INTER2 2*LINE_WIDTH /* Interval between D_SCAN Line pairs */
extern int crosshatch; /* TRUE = Crosshatch; FALSE = Solid Fill */
#define PI 3.1415927 /* define a value for pi */
#define max( A, B ) ((A) > (B) ? (A) : (B)) /* define a MAX function */
#define min( A, B ) ((A) < (B) ? (A) : (B)) /* define a MIN function */
struct DTABLE { /* declare structure for data table */
int x; /* data table x value */
int y; /* data table y value */
};
struct HATCHTABLE { /* Define Control Table for Cross Hatchs */
int df_flag; /* Flag for Double Line Fill */
int ds_flag; /* Flag for Fouble Scan Fill */
float angle1; /* Pass 1 Rotation Fill Angle */
float angle2; /* Pass 2 Rotation Fill Angle (if needed) */
};
struct edge_rec { /* define an edge table entry record */
float ymin; /* Minimum Y value for current line vector */
float ymax; /* Maximum Y value for current line vector */
float deltax; /* Slope of the current line vector */
float xval; /* X Intercept of the current line vector */
};
struct HATCHTABLE htable[] = { /* Fill Pattern Definition Table */
/* Double Double 1st 2nd Description Pattern # */
/* Fill Scan Angle Angle in Fig. 2 */
FALSE, FALSE, 0.0, 0.0, /* No Fill In This Case 1 */
FALSE, FALSE, 0.0, 0.0, /* Rotate 0 Deg. 2 */
FALSE, FALSE, -PI/4, 0.0, /* Rotate -45 Deg. 3 */
TRUE, FALSE, 0.0, PI/2, /* Rotate 0 and 90 Deg. 4 */
FALSE, FALSE, PI/4, 0.0, /* Rotate 45 Deg. 5 */
TRUE, FALSE, PI/4, -PI/4, /* Rotate ± 45 Deg. 6 */
FALSE, FALSE, PI/2, 0.0, /* Rotate 90 Deg. 7 */
TRUE, FALSE, PI/9, -PI/9, /* Rotate ± 20 Deg. 8 */
TRUE, TRUE, -PI/4, PI/4, /* Double Fill, ± 45 Deg. 9 */
TRUE, TRUE, 0.0, PI/2, /* Double Fill, 0 & 90 Deg. 10 */
FALSE, FALSE, PI/9, 0.0, /* Rotate 20 Deg. 11 */
FALSE, TRUE, PI/2, 0.0, /* Double Scan, 90 Deg. 12 */
FALSE, FALSE, -PI/9, 0.0, /* Rotate -20 Deg. 13 */
FALSE, TRUE, PI/4, 0.0, /* Double Scan, 45 Deg. 14 */
FALSE, TRUE, -PI/4, 0.0, /* Double Scan, -45 Deg. 15 */
FALSE, TRUE, 0.0, 0.0 /* Double Scan, 0 Deg. 16 */
};
struct edge_rec edge_tbl[ MAX_EDGE ]; /* Define table for edge storage */
int num_edges; /* Number of edges in edge table */
float scan_line; /* Location of current scan line to fill */
int scan_dec; /* Distance between lines in fill */
float r_angle; /* Angle of current rotation */
int d_scan, d_fill; /* Flags to control fill pattern to be used*/
int start_edge, end_edge; /* Starting and ending edge of fill line */
float fabs(); /* Declare library function for module */
polyhatch( color, points, num_points )
int color;
struct DTABLE *points;
int num_points;
{
int i, p_num;
polyline( color, points, num_points ); /* draw a border around polygon */
d_fill = d_scan = FALSE; /* assume no double scans or fills */
r_angle = 0.0; /* assume horizontal fill */
scan_dec = LINE_WIDTH; /* assume standard line width */
if( crosshatch ){
p_num = color % 16;
d_fill = htable[p_num].df_flag; /* Set Double Fill Flag */
d_scan = htable[p_num].ds_flag; /* Set Double Scan Flag */
r_angle = htable[p_num].angle1; /* Set 1st Rotation Angle */
scan_dec = 10 * LINE_WIDTH; /* Set line spacing 1st line */
}
do_fill( points, num_points );
if ( d_fill ) {
for( i=0; i<num_points; ++i ) /* Rotate data back from last pass */
rotate( -r_angle, &points[i].x, &points[i].y );
r_angle = htable[p_num].angle2; /* set second fill angle */
scan_dec = 10 * LINE_WIDTH; /* reset 1st line spacing */
do_fill( points, num_points );
}
}
/* DO_FILL: Draw in one pass of the raster scan line fill */
do_fill( data, count )
struct DTABLE *data;
int count;
{
int i;
int dsi_flag = FALSE; /* Double scan interval flag for D_SCAN */
for( i=0; i<count; ++i ) /* rotate data to scan angle for this pass */
rotate( r_angle, &data[i].x, &data[i].y );
build_table( data, count ); /* build edge table for fill */
start_edge = end_edge = 0; /* initialize counters */
scan_line = edge_tbl[0].ymax - scan_dec; /* determine 1st scan line Y */
include_edge(); /* calculate X intercepts */
update_table(); /* re-order table by X value */
while( start_edge < end_edge ){ /* Scan Line Loop */
fill_line(); /* draw current scan line */
if( d_scan ){ /* change scan_dec for D_SCAN*/
scan_dec = dsi_flag ? INTER1 : INTER2; /* set D_SCAN interval */
dsi_flag = !dsi_flag; /* toggle interval flag */
}
scan_line -= scan_dec; /* update coord of scan line */
include_edge(); /* calculate X intercepts */
update_table(); /* re-order table by X value */
}
}
/* Build the edge table from the input data coordinate pairs. */
build_table( data, count )
struct DTABLE *data;
int count;
{
float x1, x2, y1, y2, ymx;
int i, j, k;
num_edges = 0;
x1 = (float)data[0].x;
y1 = (float)data[0].y + 0.5;
for( k=1 ; k<count ; ++k ){
i = k % (count-1);
x2 = (float)data[i].x;
y2 = (float)data[i].y + 0.5;
if( fabs(y1 - y2) < ROUND_OFF ) x1 = x2; /* line is essentually horz */
else {
ymx = max( y1, y2 );
j = num_edges - 1;
while( (edge_tbl[j].ymax < ymx) && (j > -1) ){
edge_tbl[j+1].ymax = edge_tbl[j].ymax;
edge_tbl[j+1].ymin = edge_tbl[j].ymin;
edge_tbl[j+1].deltax = edge_tbl[j].deltax;
edge_tbl[j+1].xval = edge_tbl[j].xval;
--j;
}
++j;
++num_edges;
edge_tbl[j].ymax = ymx;
edge_tbl[j].ymin = min( y1, y2 );
edge_tbl[j].deltax = (x2 - x1)/(y2 - y1);
edge_tbl[j].xval = ( y1 < y2 ) ? x2 : x1;
x1 = x2;
y1 = y2;
}
}
}
/* Calculate the X interception point of all lines which have a */
/* ymax less than or equal to the y value of the current scan line. */
include_edge()
{
int i;
i = end_edge;
while( (i++ < num_edges) && (edge_tbl[end_edge+1].ymax >= scan_line) ){
edge_tbl[end_edge+1].xval = edge_tbl[end_edge+1].xval +
(edge_tbl[end_edge+1].deltax * (scan_dec + scan_line -
edge_tbl[end_edge+1].ymax));
end_edge++;
}
}
update_table()
{
int i, j, k, first_edge;
float temp, deltay;
first_edge = start_edge;
for( i=first_edge; i<end_edge; ++i ){
if( edge_tbl[i].ymin < scan_line ){
deltay = fabs( edge_tbl[i].ymax - edge_tbl[i].ymin );
deltay = min( deltay, scan_dec );
edge_tbl[i].xval = edge_tbl[i].xval - (edge_tbl[i].deltax * deltay);
k = i;
while( (k > start_edge) && (edge_tbl[k].xval < edge_tbl[k-1].xval ) ){
temp = edge_tbl[k].ymin;
edge_tbl[k].ymin = edge_tbl[k-1].ymin;
edge_tbl[k-1].ymin = temp;
temp = edge_tbl[k].deltax;
edge_tbl[k].deltax = edge_tbl[k-1].deltax;
edge_tbl[k-1].deltax = temp;
temp = edge_tbl[k].xval;
edge_tbl[k].xval = edge_tbl[k-1].xval;
edge_tbl[k-1].xval = temp;
k--;
}
}
else {
start_edge++;
if (start_edge <= i) {
for( j=i; i>start_edge; --i ){
edge_tbl[j].ymin = edge_tbl[j-1].ymin;
edge_tbl[j].xval = edge_tbl[j-1].xval;
edge_tbl[j].deltax = edge_tbl[j-1].deltax;
}
}
}
}
}
/* Draw the line segments of the current scan line to output device. */
fill_line()
{
static int line_state; /* Direction to draw current fill line */
int i, k, j = 1;
int xtmp, ytmp, inc, inc2;
i = end_edge - start_edge;
k = line_state ? end_edge : start_edge;
inc2 = 2 * (inc = line_state ? -1 : 1);
while( j <= i ){
xtmp = (int)(edge_tbl[k].xval + 0.5);
ytmp = (int)scan_line;
rotate( -r_angle, &xtmp, &ytmp );
move_abs( xtmp, ytmp );
xtmp = (int)(edge_tbl[k+inc].xval + 0.5);
ytmp = (int)scan_line;
rotate( -r_angle, &xtmp, &ytmp );
line_abs( xtmp, ytmp );
k += inc2; j += 2;
}
line_state = !line_state; /* toggle line state */
}
/* ROTATE: Rotate the X-Y Coordinate pair by the preset angle */
rotate( angle, x, y )
float angle;
int *x, *y;
{
float sinx, siny, cosx, cosy;
float sin(), cos();
static float p_angle = 0.0, p_sin = 0.0, p_cos = 1.0;
float xtemp, ytemp;
if( angle==0.0 ) return; /* no rotation required for 0.0 degrees */
if( angle != p_angle ){ /* angle has changed, calculate new values */
p_sin = sin( angle );
p_cos = cos( angle );
p_angle = angle;
}
sinx = p_sin * (float)(*x); cosx = p_cos * (float)(*x);
siny = p_sin * (float)(*y); cosy = p_cos * (float)(*y);
*x = (int)( cosx - siny ); *y = (int)( cosy + sinx );
}